package com.example.cloud.service.impl;

import com.example.cloud.dto.VideoInfo;
import com.example.cloud.service.VideoService;
import com.example.cloud.util.HttpUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.Arrays;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.JsonNode;

/**
 * 视频服务实现类
 */
@Slf4j
@Service
public class VideoServiceImpl implements VideoService {

    @Autowired
    private RestTemplate restTemplate;

    /**
     * 解析视频
     *
     * @param url 视频链接
     * @return 视频信息
     */
    @Override
    public VideoInfo parseVideo(String url) {
        try {
            log.info("开始解析视频: {}", url);
            
            // 判断视频平台类型
            if (url.contains("douyin.com") || url.contains("iesdouyin.com") || url.contains("v.douyin.com")) {
                log.info("检测到抖音视频链接");
                return parseDouyinVideo(url);
            } else if (url.contains("kuaishou.com") || url.contains("v.kuaishou.com")) {
                log.info("检测到快手视频链接");
                log.error("暂不支持快手视频解析");
                return null;
            } else if (url.contains("xiaohongshu.com") || url.contains("xhslink.com")) {
                log.info("检测到小红书视频链接");
                log.error("暂不支持小红书视频解析");
                return null;
            } else {
                log.error("不支持的视频平台: {}", url);
                return null;
            }
        } catch (Exception e) {
            log.error("解析视频失败: {}", e.getMessage(), e);
            return null;
        }
    }

    /**
     * 解析抖音视频
     *
     * @param url 视频链接
     * @return 视频信息
     */
    private VideoInfo parseDouyinVideo(String url) {
        try {
            // 1. 从URL中提取视频ID
            String videoId = extractDouyinVideoId(url);
            if (videoId == null || videoId.isEmpty()) {
                log.error("无法从URL中提取抖音视频ID: {}", url);
                return null;
            }
            
            log.info("提取到抖音视频ID: {}", videoId);
            
            // 2. 尝试直接获取媒体流
            VideoInfo videoInfo = getDouyinMediaStream(videoId);
            if (videoInfo != null) {
                return videoInfo;
            }
            
            // 3. 如果直接获取媒体流失败，尝试备用方法
            videoInfo = getDouyinMediaStreamFallback(videoId);
            if (videoInfo != null) {
                return videoInfo;
            }
            
            // 4. 如果备用方法也失败，尝试使用API方式
            videoInfo = getDouyinMediaByApi(videoId);
            if (videoInfo != null) {
                return videoInfo;
            }
            
            log.error("无法解析抖音视频: {}", url);
            return null;
        } catch (Exception e) {
            log.error("解析抖音视频失败: {}", e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 从URL中提取抖音视频ID
     *
     * @param url 抖音视频链接
     * @return 视频ID
     */
    private String extractDouyinVideoId(String url) {
        try {
            // 首先尝试获取重定向后的真实链接
            String realUrl = HttpUtil.getRedirectUrl(url);
            log.info("抖音视频重定向后的URL: {}", realUrl);
            
            // 处理各种抖音链接格式
            
            // 1. 标准网页链接格式: https://www.douyin.com/video/7123456789012345678
            Pattern standardPattern = Pattern.compile("douyin\\.com/video/([0-9]+)");
            Matcher standardMatcher = standardPattern.matcher(realUrl);
            if (standardMatcher.find()) {
                return standardMatcher.group(1);
            }
            
            // 2. 短链接格式: https://v.douyin.com/abcdefg/
            if (realUrl.contains("v.douyin.com")) {
                // 需要再次获取重定向链接
                String finalUrl = HttpUtil.getRedirectUrl(realUrl);
                log.info("抖音短链接再次重定向后的URL: {}", finalUrl);
                
                Matcher finalMatcher = standardPattern.matcher(finalUrl);
                if (finalMatcher.find()) {
                    return finalMatcher.group(1);
                }
            }
            
            // 3. 移动端链接格式: https://www.iesdouyin.com/share/video/7123456789012345678/
            Pattern mobilePattern = Pattern.compile("douyin\\.com/share/video/([0-9]+)");
            Matcher mobileMatcher = mobilePattern.matcher(realUrl);
            if (mobileMatcher.find()) {
                return mobileMatcher.group(1);
            }
            
            // 4. 直接从URL中提取数字ID
            Pattern numericPattern = Pattern.compile("/([0-9]{19})[/?]?");
            Matcher numericMatcher = numericPattern.matcher(realUrl);
            if (numericMatcher.find()) {
                return numericMatcher.group(1);
            }
            
            // 5. 如果URL本身就是纯数字ID
            if (url.matches("^[0-9]{19}$")) {
                return url;
            }
            
            log.error("无法从URL中提取抖音视频ID: {}", url);
            return null;
        } catch (Exception e) {
            log.error("提取抖音视频ID失败: {}", e.getMessage(), e);
            return null;
        }
    }

    /**
     * 解析快手视频
     *
     * @param url 快手分享链接
     * @return 视频信息
     */
    private VideoInfo parseKuaishouVideo(String url) {
        log.error("暂不支持快手视频解析");
        return null;
    }

    /**
     * 解析小红书视频
     *
     * @param url 小红书分享链接
     * @return 视频信息
     */
    private VideoInfo parseXiaohongshuVideo(String url) {
        log.error("暂不支持小红书视频解析");
        return null;
    }

    /**
     * 通过模拟浏览器请求获取抖音视频的媒体源
     *
     * @param url 抖音视频URL
     * @return 视频信息
     */
    private VideoInfo getDouyinDirectMediaSource(String url) {
        try {
            log.info("尝试模拟浏览器请求获取抖音视频媒体源: {}", url);
            
            // 1. 首先尝试直接从视频页面URL中提取视频ID
            String videoId = extractDouyinVideoId(url);
            if (videoId != null) {
                log.info("成功提取到抖音视频ID: {}", videoId);
                
                // 2. 直接获取媒体流
                return getDouyinMediaStream(videoId);
            }
            
            // 如果无法提取视频ID，尝试使用原来的HTML解析方法
            return parseDouyinVideoByHtmlParsing(url);
        } catch (Exception e) {
            log.error("模拟浏览器获取媒体源失败: {}", e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 直接获取抖音视频的媒体流
     * 
     * @param videoId 视频ID
     * @return 视频信息
     */
    private VideoInfo getDouyinMediaStream(String videoId) {
        try {
            log.info("尝试直接获取抖音视频媒体流: {}", videoId);
            
            // 1. 首先获取视频页面，以获取必要的cookie和token
            String videoPageUrl = "https://www.douyin.com/video/" + videoId;
            
            HttpHeaders pageHeaders = new HttpHeaders();
            pageHeaders.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36");
            pageHeaders.add("Referer", "https://www.douyin.com/");
            pageHeaders.add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7");
            pageHeaders.add("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8");
            
            HttpEntity<String> pageEntity = new HttpEntity<>(pageHeaders);
            ResponseEntity<String> pageResponse = restTemplate.exchange(videoPageUrl, HttpMethod.GET, pageEntity, String.class);
            String html = pageResponse.getBody();
            
            if (html != null && !html.isEmpty()) {
                // 2. 从HTML中直接提取媒体URL
                // 使用正则表达式匹配媒体URL
                // 这个正则表达式匹配类似 https://v3-web.douyinvod.com/... 的URL
                String mediaUrlPattern = "(https?://[\\w.-]+\\.douyinvod\\.com/[^\"'\\s<>]+)";
                Pattern pattern = Pattern.compile(mediaUrlPattern);
                Matcher matcher = pattern.matcher(html);
                
                if (matcher.find()) {
                    String mediaUrl = matcher.group(1);
                    // 处理转义字符
                    mediaUrl = mediaUrl.replace("\\u002F", "/");
                    log.info("从HTML中直接提取到媒体URL: {}", mediaUrl);
                    
                    // 提取标题和作者
                    String title = extractTitleFromHtml(html);
                    String author = extractAuthorFromHtml(html);
                    String coverUrl = extractCoverUrlFromHtml(html);
                    
                    return VideoInfo.builder()
                            .url(mediaUrl)
                            .title(title)
                            .author(author)
                            .platform("抖音")
                            .coverUrl(coverUrl)
                            .duration(0)
                            .build();
                }
                
                // 3. 尝试从RENDER_DATA中提取媒体URL
                String renderDataPattern = "window\\.RENDER_DATA\\s*=\\s*(['\"])([\\s\\S]*?)\\1";
                Pattern renderPattern = Pattern.compile(renderDataPattern);
                Matcher renderMatcher = renderPattern.matcher(html);
                
                if (renderMatcher.find()) {
                    try {
                        String base64Data = renderMatcher.group(2);
                        String decodedData = new String(java.util.Base64.getDecoder().decode(base64Data));
                        log.info("找到RENDER_DATA，解码后长度: {}", decodedData.length());
                        
                        // 从解码后的数据中提取媒体URL
                        Pattern mediaPattern = Pattern.compile("(https?://[\\w.-]+\\.douyinvod\\.com/[^\"'\\s<>]+)");
                        Matcher mediaMatcher = mediaPattern.matcher(decodedData);
                        
                        if (mediaMatcher.find()) {
                            String mediaUrl = mediaMatcher.group(1);
                            // 处理转义字符
                            mediaUrl = mediaUrl.replace("\\u002F", "/");
                            log.info("从RENDER_DATA中提取到媒体URL: {}", mediaUrl);
                            
                            // 提取标题和作者
                            String title = extractTitleFromRenderData(decodedData);
                            String author = extractAuthorFromRenderData(decodedData);
                            String coverUrl = extractCoverUrlFromRenderData(decodedData);
                            
                            return VideoInfo.builder()
                                    .url(mediaUrl)
                                    .title(title)
                                    .author(author)
                                    .platform("抖音")
                                    .coverUrl(coverUrl)
                                    .duration(0)
                                    .build();
                        }
                    } catch (Exception e) {
                        log.error("解析RENDER_DATA失败: {}", e.getMessage());
                    }
                }
                
                // 4. 尝试使用XG-Player标记查找媒体URL
                String xgPlayerPattern = "\"src\"\\s*:\\s*\"(https?://[\\w.-]+\\.douyinvod\\.com/[^\"]+)\"";
                Pattern xgPlayerPatternObj = Pattern.compile(xgPlayerPattern);
                Matcher xgPlayerMatcher = xgPlayerPatternObj.matcher(html);
                
                if (xgPlayerMatcher.find()) {
                    String mediaUrl = xgPlayerMatcher.group(1).replace("\\u002F", "/");
                    log.info("从XG-Player标记中提取到媒体URL: {}", mediaUrl);
                    
                    // 提取标题和作者
                    String title = extractTitleFromHtml(html);
                    String author = extractAuthorFromHtml(html);
                    String coverUrl = extractCoverUrlFromHtml(html);
                    
                    return VideoInfo.builder()
                            .url(mediaUrl)
                            .title(title)
                            .author(author)
                            .platform("抖音")
                            .coverUrl(coverUrl)
                            .duration(0)
                            .build();
                }
            }

            log.error("无法从HTML中提取媒体URL");
            return null;
        } catch (Exception e) {
            log.error("获取抖音媒体流失败: {}", e.getMessage(), e);
            return null;
        }
    }

    /**
     * 从HTML中提取视频标题
     * 
     * @param html HTML内容
     * @return 视频标题
     */
    private String extractTitleFromHtml(String html) {
        try {
            // 尝试从meta标签中提取标题
            Pattern pattern = Pattern.compile("<meta\\s+name=\"title\"\\s+content=\"([^\"]+)\"");
            Matcher matcher = pattern.matcher(html);
            if (matcher.find()) {
                return matcher.group(1);
            }
            
            // 尝试从og:title中提取
            pattern = Pattern.compile("<meta\\s+property=\"og:title\"\\s+content=\"([^\"]+)\"");
            matcher = pattern.matcher(html);
            if (matcher.find()) {
                return matcher.group(1);
            }
            
            // 尝试从title标签中提取
            pattern = Pattern.compile("<title>([^<]+)</title>");
            matcher = pattern.matcher(html);
            if (matcher.find()) {
                return matcher.group(1);
            }
            
            return "抖音视频";
        } catch (Exception e) {
            log.error("提取标题失败: {}", e.getMessage());
            return "抖音视频";
        }
    }
    
    /**
     * 从HTML中提取视频作者
     * 
     * @param html HTML内容
     * @return 视频作者
     */
    private String extractAuthorFromHtml(String html) {
        try {
            // 尝试从meta标签中提取作者
            Pattern pattern = Pattern.compile("<meta\\s+name=\"author\"\\s+content=\"([^\"]+)\"");
            Matcher matcher = pattern.matcher(html);
            if (matcher.find()) {
                return matcher.group(1);
            }
            
            // 尝试从特定的class中提取
            pattern = Pattern.compile("class=\"author-name[^\"]*\"[^>]*>([^<]+)<");
            matcher = pattern.matcher(html);
            if (matcher.find()) {
                return matcher.group(1);
            }
            
            return "抖音用户";
        } catch (Exception e) {
            log.error("提取作者失败: {}", e.getMessage());
            return "抖音用户";
        }
    }
    
    /**
     * 从HTML中提取视频封面URL
     * 
     * @param html HTML内容
     * @return 封面URL
     */
    private String extractCoverUrlFromHtml(String html) {
        try {
            // 尝试从og:image中提取
            Pattern pattern = Pattern.compile("<meta\\s+property=\"og:image\"\\s+content=\"([^\"]+)\"");
            Matcher matcher = pattern.matcher(html);
            if (matcher.find()) {
                return matcher.group(1);
            }
            
            // 尝试从poster属性中提取
            pattern = Pattern.compile("<video[^>]+poster=\"([^\"]+)\"");
            matcher = pattern.matcher(html);
            if (matcher.find()) {
                return matcher.group(1);
            }
            
            return "";
        } catch (Exception e) {
            log.error("提取封面URL失败: {}", e.getMessage());
            return "";
        }
    }
    
    /**
     * 从RENDER_DATA中提取视频标题
     * 
     * @param renderData RENDER_DATA内容
     * @return 视频标题
     */
    private String extractTitleFromRenderData(String renderData) {
        try {
            Pattern pattern = Pattern.compile("\"desc\"\\s*:\\s*\"([^\"]+)\"");
            Matcher matcher = pattern.matcher(renderData);
            if (matcher.find()) {
                return matcher.group(1).replace("\\u002F", "/");
            }
            return "抖音视频";
        } catch (Exception e) {
            log.error("从RENDER_DATA提取标题失败: {}", e.getMessage());
            return "抖音视频";
        }
    }
    
    /**
     * 从RENDER_DATA中提取视频作者
     * 
     * @param renderData RENDER_DATA内容
     * @return 视频作者
     */
    private String extractAuthorFromRenderData(String renderData) {
        try {
            Pattern pattern = Pattern.compile("\"nickname\"\\s*:\\s*\"([^\"]+)\"");
            Matcher matcher = pattern.matcher(renderData);
            if (matcher.find()) {
                return matcher.group(1).replace("\\u002F", "/");
            }
            return "抖音用户";
        } catch (Exception e) {
            log.error("从RENDER_DATA提取作者失败: {}", e.getMessage());
            return "抖音用户";
        }
    }

    /**
     * 从RENDER_DATA中提取视频封面URL
     * 
     * @param renderData RENDER_DATA内容
     * @return 封面URL
     */
    private String extractCoverUrlFromRenderData(String renderData) {
        try {
            Pattern pattern = Pattern.compile("\"cover\"\\s*:\\s*\"([^\"]+)\"");
            Matcher matcher = pattern.matcher(renderData);
            if (matcher.find()) {
                return matcher.group(1).replace("\\u002F", "/");
            }
            return "";
        } catch (Exception e) {
            log.error("从RENDER_DATA提取封面URL失败: {}", e.getMessage());
            return "";
        }
    }

    /**
     * 通过解析HTML页面获取抖音视频信息
     */
    private VideoInfo parseDouyinVideoByHtmlParsing(String url) {
        try {
            log.info("尝试通过解析HTML获取抖音视频信息: {}", url);
            
            // 设置完整的请求头，模拟真实浏览器
            HttpHeaders headers = new HttpHeaders();
            headers.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36");
            headers.add("Referer", "https://www.douyin.com/");
            headers.add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7");
            headers.add("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8");
            headers.add("Cache-Control", "max-age=0");
            headers.add("Connection", "keep-alive");
            headers.add("Upgrade-Insecure-Requests", "1");
            headers.add("Sec-Fetch-Dest", "document");
            headers.add("Sec-Fetch-Mode", "navigate");
            headers.add("Sec-Fetch-Site", "none");
            headers.add("Sec-Fetch-User", "?1");
            headers.add("Cookie", "s_v_web_id=verify_lp6xgxz8_HxCV1m9n_TgXH_4Qcf_9Yxs_KDfUTX60QDzm; passport_csrf_token=42a31a96d246b4d243c3440a739383b1; ttwid=1%7CWBuxH_bhbuTENNtACXoesI5QHV2Dt9-vkMGVHSRRbgY%7C1690789000%7C1d87ba1ea2cdf05d80204aea2e1036451dae638e7f2a21c9e85d653a75a99419; douyin.com; device_web_cpu_core=8; device_web_memory_size=8; architecture=amd64; dy_swidth=1920; dy_sheight=1080");
            
            HttpEntity<String> entity = new HttpEntity<>(headers);
            
            // 发送请求获取HTML内容
            ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.GET, entity, String.class);
            String html = response.getBody();
            
            if (html != null && !html.isEmpty()) {
                log.info("成功获取到HTML内容，长度: {}", html.length());
                
                // 1. 尝试从HTML中提取JSON数据
                // 抖音通常在页面中嵌入一个包含视频信息的JSON数据
                String jsonPattern = "window\\.__INIT_PROPS__\\s*=\\s*(\\{.*?\\});</script>";
                Pattern pattern = Pattern.compile(jsonPattern, Pattern.DOTALL);
                Matcher matcher = pattern.matcher(html);
                
                if (matcher.find()) {
                    String jsonStr = matcher.group(1);
                    log.info("找到JSON数据，长度: {}", jsonStr.length());
                    
                    // 解析JSON数据
                    ObjectMapper mapper = new ObjectMapper();
                    try {
                        Map<String, Object> jsonData = mapper.readValue(jsonStr, Map.class);
                        
                        // 从JSON中提取视频信息
                        // 注意：抖音的JSON结构可能会变化，需要根据实际情况调整
                        if (jsonData.containsKey("initialData")) {
                            Map<String, Object> initialData = (Map<String, Object>) jsonData.get("initialData");
                            
                            if (initialData.containsKey("aweme")) {
                                Map<String, Object> aweme = (Map<String, Object>) initialData.get("aweme");
                                
                                if (aweme.containsKey("detail")) {
                                    Map<String, Object> detail = (Map<String, Object>) aweme.get("detail");
                                    
                                    // 提取视频URL
                                    String videoUrl = extractVideoUrlFromJson(detail);
                                    String title = extractTitleFromJson(detail);
                                    String author = extractAuthorFromJson(detail);
                                    String coverUrl = extractCoverUrlFromJson(detail);
                                    
                                    if (videoUrl != null && !videoUrl.isEmpty()) {
                                        log.info("成功从JSON中提取视频信息: title={}, author={}, videoUrl={}", title, author, videoUrl);
                                        
                                        return VideoInfo.builder()
                                                .url(videoUrl)
                                                .title(title)
                                                .author(author)
                                                .platform("抖音")
                                                .coverUrl(coverUrl)
                                                .duration(0)
                                                .build();
                                    }
                                }
                            }
                        }
                    } catch (Exception e) {
                        log.error("解析JSON数据失败: {}", e.getMessage(), e);
                    }
                }
                
                // 2. 如果JSON解析失败，尝试直接从HTML中提取视频URL
                // 查找视频URL的正则表达式
                String videoUrlPattern = "\"playAddr\":\\[\\{\"src\":\"(https://[^\"]+)\"";
                Pattern videoPattern = Pattern.compile(videoUrlPattern);
                Matcher videoMatcher = videoPattern.matcher(html);
                
                if (videoMatcher.find()) {
                    String videoUrl = videoMatcher.group(1).replace("\\u002F", "/");
                    log.info("从HTML中直接提取到视频URL: {}", videoUrl);
                    
                    // 提取标题
                    String titlePattern = "\"desc\":\"([^\"]+)\"";
                    Pattern titlePatternObj = Pattern.compile(titlePattern);
                    Matcher titleMatcher = titlePatternObj.matcher(html);
                    String title = titleMatcher.find() ? titleMatcher.group(1) : "抖音视频";
                    
                    // 提取作者
                    String authorPattern = "\"nickname\":\"([^\"]+)\"";
                    Pattern authorPatternObj = Pattern.compile(authorPattern);
                    Matcher authorMatcher = authorPatternObj.matcher(html);
                    String author = authorMatcher.find() ? authorMatcher.group(1) : "未知作者";
                    
                    // 提取封面
                    String coverPattern = "\"cover\":\"(https://[^\"]+)\"";
                    Pattern coverPatternObj = Pattern.compile(coverPattern);
                    Matcher coverMatcher = coverPatternObj.matcher(html);
                    String coverUrl = coverMatcher.find() ? coverMatcher.group(1).replace("\\u002F", "/") : "";
                    
                    return VideoInfo.builder()
                            .url(videoUrl)
                            .title(title)
                            .author(author)
                            .platform("抖音")
                            .coverUrl(coverUrl)
                            .duration(0)
                            .build();
                }
                
                // 3. 尝试查找包含视频信息的其他JSON结构
                String renderDataPattern = "window\\.RENDER_DATA\\s*=\\s*(['\"])([\\s\\S]*?)\\1";
                Pattern renderPattern = Pattern.compile(renderDataPattern);
                Matcher renderMatcher = renderPattern.matcher(html);
                
                if (renderMatcher.find()) {
                    String base64Data = renderMatcher.group(2);
                    String decodedData = new String(java.util.Base64.getDecoder().decode(base64Data));
                    log.info("找到RENDER_DATA，解码后长度: {}", decodedData.length());
                    
                    // 从解码后的数据中提取视频URL
                    String renderVideoPattern = "\"playAddr\":\"(https://[^\"]+)\"";
                    Pattern renderVideoPatternObj = Pattern.compile(renderVideoPattern);
                    Matcher renderVideoMatcher = renderVideoPatternObj.matcher(decodedData);
                    
                    if (renderVideoMatcher.find()) {
                        String videoUrl = renderVideoMatcher.group(1).replace("\\u002F", "/");
                        log.info("从RENDER_DATA中提取到视频URL: {}", videoUrl);
                        
                        // 提取标题
                        String titlePattern = "\"desc\":\"([^\"]+)\"";
                        Pattern titlePatternObj = Pattern.compile(titlePattern);
                        Matcher titleMatcher = titlePatternObj.matcher(decodedData);
                        String title = titleMatcher.find() ? titleMatcher.group(1) : "抖音视频";
                        
                        // 提取作者
                        String authorPattern = "\"nickname\":\"([^\"]+)\"";
                        Pattern authorPatternObj = Pattern.compile(authorPattern);
                        Matcher authorMatcher = authorPatternObj.matcher(decodedData);
                        String author = authorMatcher.find() ? authorMatcher.group(1) : "未知作者";
                        
                        // 提取封面
                        String coverPattern = "\"cover\":\"(https://[^\"]+)\"";
                        Pattern coverPatternObj = Pattern.compile(coverPattern);
                        Matcher coverMatcher = coverPatternObj.matcher(decodedData);
                        String coverUrl = coverMatcher.find() ? coverMatcher.group(1).replace("\\u002F", "/") : "";
                        
                        return VideoInfo.builder()
                                .url(videoUrl)
                                .title(title)
                                .author(author)
                                .platform("抖音")
                                .coverUrl(coverUrl)
                                .duration(0)
                                .build();
                    }
                }
            }
            
            log.warn("无法从HTML中提取视频信息");
            return null;
        } catch (Exception e) {
            log.error("解析HTML获取视频信息失败: {}", e.getMessage(), e);
            return null;
        }
    }
    
    /**
     * 从JSON中提取视频URL
     */
    private String extractVideoUrlFromJson(Map<String, Object> detail) {
        try {
            if (detail.containsKey("video")) {
                Map<String, Object> video = (Map<String, Object>) detail.get("video");
                
                if (video.containsKey("playAddr")) {
                    List<Map<String, Object>> playAddrs = (List<Map<String, Object>>) video.get("playAddr");
                    
                    if (!playAddrs.isEmpty() && playAddrs.get(0).containsKey("src")) {
                        return (String) playAddrs.get(0).get("src");
                    }
                } else if (video.containsKey("play_addr")) {
                    Map<String, Object> playAddr = (Map<String, Object>) video.get("play_addr");
                    
                    if (playAddr.containsKey("url_list") && playAddr.get("url_list") instanceof List) {
                        List<String> urlList = (List<String>) playAddr.get("url_list");
                        
                        if (!urlList.isEmpty()) {
                            return urlList.get(0);
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("从JSON提取视频URL失败: {}", e.getMessage());
        }
        return null;
    }
    
    /**
     * 从JSON中提取视频标题
     */
    private String extractTitleFromJson(Map<String, Object> detail) {
        try {
            if (detail.containsKey("desc")) {
                return (String) detail.get("desc");
            }
        } catch (Exception e) {
            log.error("从JSON提取标题失败: {}", e.getMessage());
        }
        return "抖音视频";
    }
    
    /**
     * 从JSON中提取作者信息
     */
    private String extractAuthorFromJson(Map<String, Object> detail) {
        try {
            if (detail.containsKey("author") && detail.get("author") instanceof Map) {
                Map<String, Object> author = (Map<String, Object>) detail.get("author");
                
                if (author.containsKey("nickname")) {
                    return (String) author.get("nickname");
                }
            }
        } catch (Exception e) {
            log.error("从JSON提取作者失败: {}", e.getMessage());
        }
        return "未知作者";
    }
    
    /**
     * 从JSON中提取封面URL
     */
    private String extractCoverUrlFromJson(Map<String, Object> detail) {
        try {
            if (detail.containsKey("video") && detail.get("video") instanceof Map) {
                Map<String, Object> video = (Map<String, Object>) detail.get("video");
                
                if (video.containsKey("cover") && video.get("cover") instanceof Map) {
                    Map<String, Object> cover = (Map<String, Object>) video.get("cover");
                    
                    if (cover.containsKey("url_list") && cover.get("url_list") instanceof List) {
                        List<String> urlList = (List<String>) cover.get("url_list");
                        
                        if (!urlList.isEmpty()) {
                            return urlList.get(0);
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("从JSON提取封面URL失败: {}", e.getMessage());
        }
        return "";
    }

    /**
     * 备用方法：尝试使用更多的正则表达式模式来提取抖音视频媒体流
     * 
     * @param videoId 视频ID
     * @return 视频信息
     */
    private VideoInfo getDouyinMediaStreamFallback(String videoId) {
        try {
            log.info("尝试使用备用方法获取抖音视频媒体流: {}", videoId);
            
            // 1. 获取视频页面
            String videoPageUrl = "https://www.douyin.com/video/" + videoId;
            
            HttpHeaders pageHeaders = new HttpHeaders();
            pageHeaders.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36");
            pageHeaders.add("Referer", "https://www.douyin.com/");
            pageHeaders.add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7");
            pageHeaders.add("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8");
            
            HttpEntity<String> pageEntity = new HttpEntity<>(pageHeaders);
            ResponseEntity<String> pageResponse = restTemplate.exchange(videoPageUrl, HttpMethod.GET, pageEntity, String.class);
            String html = pageResponse.getBody();
            
            if (html != null && !html.isEmpty()) {
                // 2. 尝试多种正则表达式模式
                List<String> patterns = Arrays.asList(
                    // 模式1: 标准douyinvod.com URL
                    "(https?://[\\w.-]+\\.douyinvod\\.com/[^\"'\\s<>]+)",
                    // 模式2: 查找带有play_url的JSON片段
                    "\"play_url\"\\s*:\\s*\"(https?://[^\"]+)\"",
                    // 模式3: 查找带有video_url的JSON片段
                    "\"video_url\"\\s*:\\s*\"(https?://[^\"]+)\"",
                    // 模式4: 查找带有src属性的video标签
                    "<video[^>]+src=\"(https?://[^\"]+)\"",
                    // 模式5: 查找带有url属性的JSON片段
                    "\"url\"\\s*:\\s*\"(https?://[^\"]+\\.mp4[^\"]*)\""
                );
                
                for (String patternStr : patterns) {
                    Pattern pattern = Pattern.compile(patternStr);
                    Matcher matcher = pattern.matcher(html);
                    
                    if (matcher.find()) {
                        String mediaUrl = matcher.group(1);
                        // 处理转义字符
                        mediaUrl = mediaUrl.replace("\\u002F", "/");
                        log.info("使用模式 '{}' 提取到媒体URL: {}", patternStr, mediaUrl);
                        
                        // 提取标题和作者
                        String title = extractTitleFromHtml(html);
                        String author = extractAuthorFromHtml(html);
                        String coverUrl = extractCoverUrlFromHtml(html);
                        
                        return VideoInfo.builder()
                                .url(mediaUrl)
                                .title(title)
                                .author(author)
                                .platform("抖音")
                                .coverUrl(coverUrl)
                                .duration(0)
                                .build();
                    }
                }
                
                // 3. 尝试从页面中提取playJson
                String playJsonPattern = "\"playJson\"\\s*:\\s*\"([^\"]+)\"";
                Pattern playJsonPatternObj = Pattern.compile(playJsonPattern);
                Matcher playJsonMatcher = playJsonPatternObj.matcher(html);
                
                if (playJsonMatcher.find()) {
                    try {
                        String encodedJson = playJsonMatcher.group(1);
                        // 解码JSON字符串
                        String decodedJson = encodedJson.replace("\\u002F", "/")
                                                       .replace("\\\"", "\"")
                                                       .replace("\\\\", "\\");
                        
                        log.info("找到playJson，解码后: {}", decodedJson);
                        
                        // 从解码后的JSON中提取媒体URL
                        Pattern mediaPattern = Pattern.compile("(https?://[^\"]+\\.mp4[^\"]*)");
                        Matcher mediaMatcher = mediaPattern.matcher(decodedJson);
                        
                        if (mediaMatcher.find()) {
                            String mediaUrl = mediaMatcher.group(1);
                            log.info("从playJson中提取到媒体URL: {}", mediaUrl);
                            
                            // 提取标题和作者
                            String title = extractTitleFromHtml(html);
                            String author = extractAuthorFromHtml(html);
                            String coverUrl = extractCoverUrlFromHtml(html);
                            
                            return VideoInfo.builder()
                                    .url(mediaUrl)
                                    .title(title)
                                    .author(author)
                                    .platform("抖音")
                                    .coverUrl(coverUrl)
                                    .duration(0)
                                    .build();
                        }
                    } catch (Exception e) {
                        log.error("解析playJson失败: {}", e.getMessage());
                    }
                }
            }
            
            log.error("备用方法无法提取媒体URL");
            return null;
        } catch (Exception e) {
            log.error("备用方法获取抖音媒体流失败: {}", e.getMessage(), e);
            return null;
        }
    }

    /**
     * 最后的备用方案：使用抖音API解析视频
     * 
     * @param videoId 视频ID
     * @return 视频信息
     */
    private VideoInfo getDouyinMediaByApi(String videoId) {
        try {
            log.info("尝试使用API方式获取抖音视频: {}", videoId);
            
            // 构建API请求URL
            String apiUrl = "https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids=" + videoId;
            
            HttpHeaders headers = new HttpHeaders();
            headers.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36");
            headers.add("Referer", "https://www.douyin.com/");
            headers.add("Accept", "application/json");
            
            HttpEntity<String> entity = new HttpEntity<>(headers);
            ResponseEntity<String> response = restTemplate.exchange(apiUrl, HttpMethod.GET, entity, String.class);
            
            if (response.getStatusCode().is2xxSuccessful()) {
                String jsonResponse = response.getBody();
                if (jsonResponse != null && !jsonResponse.isEmpty()) {
                    // 解析JSON响应
                    ObjectMapper mapper = new ObjectMapper();
                    JsonNode rootNode = mapper.readTree(jsonResponse);
                    
                    // 检查API响应状态
                    if (rootNode.has("status_code") && rootNode.get("status_code").asInt() == 0) {
                        // 获取视频信息
                        if (rootNode.has("item_list") && rootNode.get("item_list").isArray() && rootNode.get("item_list").size() > 0) {
                            JsonNode itemNode = rootNode.get("item_list").get(0);
                            
                            // 提取视频标题
                            String title = "";
                            if (itemNode.has("desc")) {
                                title = itemNode.get("desc").asText();
                            }
                            
                            // 提取作者信息
                            String author = "";
                            if (itemNode.has("author") && itemNode.get("author").has("nickname")) {
                                author = itemNode.get("author").get("nickname").asText();
                            }
                            
                            // 提取封面URL
                            String coverUrl = "";
                            if (itemNode.has("video") && itemNode.get("video").has("cover") && 
                                itemNode.get("video").get("cover").has("url_list") && 
                                itemNode.get("video").get("cover").get("url_list").isArray() && 
                                itemNode.get("video").get("cover").get("url_list").size() > 0) {
                                coverUrl = itemNode.get("video").get("cover").get("url_list").get(0).asText();
                            }
                            
                            // 提取无水印视频URL
                            String videoUrl = "";
                            if (itemNode.has("video") && itemNode.get("video").has("play_addr") && 
                                itemNode.get("video").get("play_addr").has("url_list") && 
                                itemNode.get("video").get("play_addr").get("url_list").isArray() && 
                                itemNode.get("video").get("play_addr").get("url_list").size() > 0) {
                                // 获取第一个URL
                                videoUrl = itemNode.get("video").get("play_addr").get("url_list").get(0).asText();
                                
                                // 替换域名以获取无水印版本
                                videoUrl = videoUrl.replace("playwm", "play");
                                videoUrl = videoUrl.replace("aweme.snssdk.com", "api.amemv.com");
                                
                                // 获取最终的无水印URL（可能需要再次跟随重定向）
                                String finalVideoUrl = HttpUtil.getRedirectUrl(videoUrl);
                                if (finalVideoUrl != null && !finalVideoUrl.isEmpty()) {
                                    videoUrl = finalVideoUrl;
                                }
                            }
                            
                            if (!videoUrl.isEmpty()) {
                                log.info("成功通过API获取抖音视频URL: {}", videoUrl);
                                
                                return VideoInfo.builder()
                                        .url(videoUrl)
                                        .title(title)
                                        .author(author)
                                        .platform("抖音")
                                        .coverUrl(coverUrl)
                                        .duration(0)
                                        .build();
                            }
                        }
                    }
                }
            }
            
            log.error("API方式获取抖音视频失败");
            return null;
        } catch (Exception e) {
            log.error("API方式获取抖音视频失败: {}", e.getMessage(), e);
            return null;
        }
    }
} 